package com.ygqh.baby.service.impl;

import com.ygqh.baby.ao.*;
import com.ygqh.baby.mapper.YgCouponDetailMapper;
import com.ygqh.baby.model.YgCouponModel;
import com.ygqh.baby.po.YgCoupon;
import com.ygqh.baby.po.YgCouponDetail;
import com.ygqh.baby.po.YgCouponDetailExample;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.service.YgCouponDetailService;
import com.ygqh.baby.service.YgCouponService;
import com.ygqh.baby.service.YgUserService;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.YgStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class YgCouponDetailServiceImpl implements YgCouponDetailService {
	protected final Logger logger = Logger.getLogger(this.getClass());
	@Autowired
	private YgCouponDetailMapper ygCouponDetailMapper;
	@Autowired
	private DocumentConstant documentConstant;
	@Autowired
	private YgCouponService couponService;
	@Autowired
	private YgUserService userService;

	@Override
	public List<YgCouponDetail> find() {
		YgCouponDetailExample example = new YgCouponDetailExample();
		example.createCriteria().andStatusNotEqualTo(DataStatus.Delete.name());
		return ygCouponDetailMapper.selectByExample(example);
	}

	@Override
	public int findCount() {
		YgCouponDetailExample example = new YgCouponDetailExample();
		example.createCriteria().andStatusNotEqualTo(DataStatus.Delete.name());
		return ygCouponDetailMapper.countByExample(example);
	}

	@Override
	public YgCouponDetail findById(Long id, Long userId) {
		return ygCouponDetailMapper.selectById(id, userId);
	}

	@Override
	public int save(YgCouponDetail ygCouponDetail) {
		return ygCouponDetailMapper.insertSelective(ygCouponDetail);
	}

	@Override
	public int update(YgCouponDetail ygCouponDetail) {
		return ygCouponDetailMapper.updateByPrimaryKeySelective(ygCouponDetail);
	}

	@Override
	public ResultSet<YgCouponDetail> search(QueryInfo queryInfo, Long supplierId, CouponStatus cStatus, String q, Long couponBatchId, String userName) {
		Long[] batchIds = null;
		if (couponBatchId != null) {
			batchIds = new Long[] { couponBatchId };
		}
		List<YgCouponDetail> list = ygCouponDetailMapper.selectSuper(queryInfo, supplierId, null, cStatus, q, batchIds, null, null, userName, false);
		int count = ygCouponDetailMapper.countSuper(supplierId, null, cStatus, q, batchIds, null, null, userName, false);
		ResultSet<YgCouponDetail> resultSet = new ResultSet<YgCouponDetail>(count, list);
		return resultSet;
	}

	@Override
	public ResultSet<YgCouponDetail> search(QueryInfo queryInfo, Long supplierId, CouponType couponType, CouponStatus cStatus, Long[] batchIds, String q,
			Date startDate, Date endDate, String mobile, Boolean isReissue) {
		List<YgCouponDetail> list = ygCouponDetailMapper.selectSuper(queryInfo, supplierId, couponType, cStatus, q, batchIds, startDate, endDate, mobile,
				isReissue);
		int count = ygCouponDetailMapper.countSuper(supplierId, couponType, cStatus, q, batchIds, startDate, endDate, mobile, isReissue);
		ResultSet<YgCouponDetail> resultSet = new ResultSet<YgCouponDetail>(count, list);
		return resultSet;
	}

	@Override
	public int deleteSoft(Long[] ids, Long userId) {
		Assert.notEmpty(ids);
		YgCouponDetailExample example = new YgCouponDetailExample();
		example.createCriteria().andIdIn(Arrays.asList(ids)).andStatusEqualTo(DataStatus.Valid.name()).andUserIdEqualTo(userId);
		YgCouponDetail record = new YgCouponDetail();
		record.setStatus(DataStatus.Delete);
		return ygCouponDetailMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int deleteSoft(Long id, Long userId) {
		return this.deleteSoft(new Long[] { id }, userId);
	}

	@Override
	public int saveOrUpdate(YgCouponDetail ygCouponDetail) {
		int r = 0;
		if (ygCouponDetail.getId() != null) {
			r = this.update(ygCouponDetail);
		} else {
			r = this.save(ygCouponDetail);
		}
		return r;
	}

	@Override
	public int addCouponDetailBatch(List<YgCouponDetail> detailList) {
		if (CollectionUtils.isEmpty(detailList)) {
			return 0;
		}
		List<YgCouponDetail> list = new ArrayList<YgCouponDetail>();
		for (int i = 0; i < detailList.size(); i++) {
			list.add(detailList.get(i));
			if (i % 5000 == 0 || i == detailList.size() - 1) {
				ygCouponDetailMapper.insertCouponDetailBatch(list);
				list.clear();
			}
		}

		return 1;
	}

	@Override
	public YgCouponDetail findByCouponCode(String couponCode, Long userId) {
		return ygCouponDetailMapper.selectByCouponCode(couponCode, userId);
	}

	@Override
	public Message receiveCoupon(Long couponBatchId, YgUser user) {
		YgCoupon coupon = couponService.findById(couponBatchId);
		if (coupon.getCouponType().equals(CouponType.Constant)) {
			return receiveConstantCoupon(coupon, user);
		} else {
			return receivePostponeCoupon(coupon, user);
		}
	}

	@Override
	public Message receiveCoupon(Long couponBatchId, Date endDate, YgUser user) {
		YgCoupon coupon = couponService.findById(couponBatchId);
		if (coupon.getCouponType().equals(CouponType.Constant)) {
			return receiveConstantCoupon(coupon, user);
		} else {
			return receivePostponeCoupon(coupon, endDate, user);
		}
	}

	@Override
	public Message distributeCoupon(Long couponBatchId, String username, String remark, String executor) {
		if (StringUtils.isBlank(username)) {
			return Message.error("用户名不能为空", null);
		}
		List<String> userNameList = new ArrayList<>();
		for (String s : username.split(",")) {
			if (StringUtils.isBlank(s)) {
				continue;
			}
			userNameList.add(s.trim());
		}
		List<YgUser> userList = userService.findUsersByUserNames(userNameList);
		if (CollectionUtils.isEmpty(userList)) {
			return Message.error("用户不存在", null);
		}
		YgCoupon coupon = couponService.findById(couponBatchId);
		coupon.setCreateBy(executor);
		coupon.setCreateTime(new Date());
		coupon.setRemark(remark);
		coupon.setStartDate(new Date());
		if (coupon.getEndDate() == null) {
			Date endDate = DateConvertUtils.addDay(new Date(), coupon.getPostponeDays().intValue());
			coupon.setEndDate(endDate);
		}
		// 每次处理100条数据
		List<YgUser> recordList = new ArrayList<>(100);
		for (int i = 0; i < userList.size(); i++) {
			YgUser user = userList.get(i);
			recordList.add(user);
			userNameList.remove(user.getUserName());
			if (recordList.size() == 100 || i == userList.size() - 1) {
				ygCouponDetailMapper.insertCouponDetailBatchToUser(recordList, coupon);
				recordList.clear();
			}
		}
		if (userNameList.size() > 0) {
			return Message.error("部分用户发放失败，用户信息不存在", userNameList);
		}
		return Message.success(null);
	}

	// 固定优惠券
	private Message receiveConstantCoupon(YgCoupon coupon, YgUser user) {
		// 优惠券为空
		if (coupon == null) {
			return Message.error(documentConstant.COUPON_GRAB_EMPTY, null);
		}

		if (coupon.getReceiveType().compareTo(1) == 0) { // 仅限新用户
			Boolean newCustom = userService.isNewCustom(user.getId());
			if (!newCustom) {
				return Message.error(documentConstant.COUPON_ONLY_NEW, null);
			}
		} else if (coupon.getReceiveType().compareTo(2) == 0 && !user.isUserAgent()) { // 仅限新女王
			return Message.error(documentConstant.COUPON_ONLY_USERAGENT, null);
		}

		long currentDate = DateConvertUtils.getDateStart(new Date()).getTime();
		long endDate = coupon.getEndDate().getTime();
		// 优惠券失效
		if (currentDate - endDate > 0) {
			return Message.error(documentConstant.COUPON_IS_INVALID, null);
		}

		// 这里会有并发问题
		if (coupon.getSendNum() != null) {
			int num = ygCouponDetailMapper.selectCountByCouponBatchId(coupon.getId(), null);
			if (coupon.getSendNum().longValue() <= num) {
				return Message.error("优惠券已抢完！", num);
			}

		}
		if (coupon.getLeadNum().intValue() > 0) {
			int num = ygCouponDetailMapper.selectCountByCouponBatchId(coupon.getId(), user.getId());
			// 已经领过
			if (num >= coupon.getLeadNum()) {

				return Message.error(documentConstant.COUPON_MAXIMUN_IS_REACHED, null);
			}
		}

		long detailId = ygCouponDetailMapper.selectTopByCouponId(coupon.getId());
		YgCouponDetail detail = new YgCouponDetail();
		detail.setId(detailId);
		detail.setUserId(user.getId());
		detail.setUserName(user.getUserName());
		detail.setLeadTime(new Date());
		detail.setUseStatus(CouponStatus.Received);
		ygCouponDetailMapper.updateByPrimaryKeySelective(detail);
		// 领取成功
		return Message.success(documentConstant.COUPON_RECEIVE_SUCCESS, detail);
	}

	// 顺延优惠券
	private Message receivePostponeCoupon(YgCoupon coupon, YgUser user) {
		Date endDate = null;
		if (coupon.getStartDate() != null) {
			endDate = coupon.getEndDate();
		} else {
			endDate = DateConvertUtils.addDay(new Date(), coupon.getPostponeDays().intValue() - 1);
		}
		return this.receivePostponeCoupon(coupon, endDate, user);
	}

	private Message receivePostponeCoupon(YgCoupon coupon, Date endDate, YgUser user) {
		Assert.notNull(endDate);
		YgCouponDetail detail = new YgCouponDetail();
		Message checkCoupon = checkCoupon(coupon, user);
		if (checkCoupon.getType().equals(Message.Type.error)) {
			return checkCoupon;
		}

		detail.setCouponBatchId(coupon.getId());
		detail.setCouponCode(YgStringUtils.getRandomString(12).toUpperCase());
		detail.setUserId(user.getId());
		detail.setUserName(user.getUserName());
		detail.setFaceValue(coupon.getFaceValue());
		detail.setLeadTime(new Date());
		detail.setStartDate(coupon.getStartDate() == null ? new Date() : coupon.getStartDate());
		detail.setEndDate(endDate);
		detail.setUseStatus(CouponStatus.Received);
		ygCouponDetailMapper.insertSelective(detail);

		return Message.success(documentConstant.COUPON_RECEIVE_SUCCESS, detail);
	}

	private Message checkCoupon(YgCoupon coupon, YgUser user) {
		// 优惠券为空
		if (coupon == null) {
			return Message.error(documentConstant.COUPON_GRAB_EMPTY, null);
		}

		if (coupon.getReceiveType().compareTo(1) == 0) { // 仅限新用户
			Boolean newCustom;
			if (SalesPlatform.Yijiadian.equals(coupon.getSalesPlatform())) {
				newCustom = userService.isNewCustomByYijiadian(user.getId());
			} else {
				newCustom = userService.isNewCustom(user.getId());
			}
			if (!newCustom) {
				return Message.error(documentConstant.COUPON_ONLY_NEW, null);
			}
		} else if (coupon.getReceiveType().compareTo(2) == 0 && !user.isUserAgent()) { // 仅限新女王
			return Message.error(documentConstant.COUPON_ONLY_USERAGENT, null);
		}

		if (coupon.getEndDate() != null) {// 如果该优惠券有结束日期限制，校验有效期
			long currentDate = DateConvertUtils.getDateStart(new Date()).getTime();
			long endDate = coupon.getEndDate().getTime();
			// 优惠券失效
			if (currentDate - endDate > 0) {
				return Message.error(documentConstant.COUPON_IS_INVALID, null);
			}
		}
		// 这里会有并发问题
		if (coupon.getSendNum() != null) {
			int num = ygCouponDetailMapper.selectCountByCouponBatchId(coupon.getId(), null);
			if (coupon.getSendNum().longValue() <= num) {
				return Message.error("优惠券已抢完！", num);
			}

		}

		if (coupon.getLeadNum().intValue() > 0) {
			int num = ygCouponDetailMapper.selectCountByCouponBatchId(coupon.getId(), user.getId());
			// 已经领过
			if (num >= coupon.getLeadNum()) {

				return Message.error(documentConstant.COUPON_MAXIMUN_IS_REACHED, null);
			}
		}
		return Message.success(null);
	}

	// 保存顺延优惠劵 返回保存的id
	public Long usePostponeCoupon(YgCoupon coupon, YgUser user) {
		YgCouponDetail detail = new YgCouponDetail();
		detail.setCouponBatchId(coupon.getId());
		detail.setCouponCode(YgStringUtils.getRandomString(12).toUpperCase());
		detail.setUserId(user.getId());
		detail.setUserName(user.getUserName());
		detail.setFaceValue(coupon.getFaceValue());
		detail.setLeadTime(new Date());
		detail.setStartDate(new Date());
		Date endDate = DateConvertUtils.addDay(new Date(), coupon.getPostponeDays().intValue() - 1);
		detail.setEndDate(endDate);
		detail.setUseStatus(CouponStatus.Received);
		ygCouponDetailMapper.insertSelective(detail);
		return detail.getId();
	}

	@Override
	public List<YgCouponDetail> findByCouponBatchId(Long couponBatchId, Long userId) {
		return ygCouponDetailMapper.selectByCouponBatchId(couponBatchId, userId);

	}

	@Override
	public int updateBatch(List<YgCouponDetail> couponList) {
		int row = 0;
		if (couponList != null && couponList.size() > 0) {
			row = ygCouponDetailMapper.updateBatch(couponList);

		}
		return row;
	}

	@Override
	public Message receiveIncreateCoupon(Long couponBatchId, YgUser user) {
		YgCoupon coupon = couponService.findById(couponBatchId);
		Long couponDetailId = usePostponeCoupon(coupon, user);
		if (couponDetailId >= 1)
			return Message.success(couponDetailId);
		return Message.error(null);

	}

	@Override
	public int addPostponeCouponDetailBatch(List<YgCouponDetail> detailList) {
		if (CollectionUtils.isEmpty(detailList)) {
			return 0;
		}
		List<YgCouponDetail> list = new ArrayList<YgCouponDetail>();
		for (int i = 0; i < detailList.size(); i++) {
			list.add(detailList.get(i));
			if (i % 5000 == 0 || i == detailList.size() - 1) {
				ygCouponDetailMapper.insertPostponeCouponDetailBatch(list);
				list.clear();
			}
		}

		return 1;
	}

	@Override
	public Message receiveCouponWithRemark(Long couponBatchId, String remark, YgUser user) {
		YgCoupon coupon = couponService.findById(couponBatchId);
		Message message = checkCoupon(coupon, user);
		if (!message.getType().equals(Message.Type.success)) {
			return message;
		}
		YgCouponDetail detail = new YgCouponDetail();
		if (coupon.getStartDate() != null) {
			detail.setStartDate(coupon.getStartDate());
			detail.setEndDate(coupon.getEndDate());
		} else {
			Date endDate = DateConvertUtils.addDay(new Date(), coupon.getPostponeDays().intValue() - 1);
			detail.setStartDate(new Date());
			detail.setEndDate(endDate);
		}
		detail.setCouponBatchId(coupon.getId());
		detail.setCouponCode(YgStringUtils.getRandomString(12).toUpperCase());
		detail.setUserId(user.getId());
		detail.setUserName(user.getUserName());
		detail.setFaceValue(coupon.getFaceValue());
		detail.setLeadTime(new Date());
		detail.setUseStatus(CouponStatus.Received);
		detail.setRemark(remark);
		ygCouponDetailMapper.insertSelective(detail);
		detail.setCoupon(coupon);
		return Message.success(detail);
	}

	@Override
	public int transferCoupon(Long sourceUserId, Long targetUserId) {
		YgCouponDetailExample example = new YgCouponDetailExample();
		example.createCriteria().andUserIdEqualTo(sourceUserId);
		YgCouponDetail d = new YgCouponDetail();
		d.setUserId(targetUserId);

		return ygCouponDetailMapper.updateByExampleSelective(d, example);
	}

	@Override
	public Message sendBatchCoupon(YgCoupon coupon, List<YgUser> userList) {
		List<YgCouponDetail> detailList = new ArrayList<>();
		Date startDate = coupon.getStartDate() == null ? new Date() : coupon.getStartDate();
		Date endDate = coupon.getEndDate() == null ? DateConvertUtils.addDay(new Date(), coupon.getPostponeDays().intValue()) : coupon.getEndDate();
		for (YgUser user : userList) {
			YgCouponDetail detail = new YgCouponDetail();
			detail.setCouponBatchId(coupon.getId());
			detail.setCouponCode(YgStringUtils.getRandomString(12).toUpperCase());
			detail.setUserId(user.getId());
			detail.setUserName(user.getUserName());
			detail.setFaceValue(coupon.getFaceValue());
			detail.setLeadTime(new Date());
			detail.setOnLine(Boolean.TRUE);
			detail.setStartDate(startDate);
			detail.setEndDate(endDate);
			detail.setUseStatus(CouponStatus.Received);
			detailList.add(detail);
		}
		if (this.addPostponeCouponDetailBatch(detailList) > 0) {
			return Message.success(userList.size());
		}
		return Message.error("保存优惠券明细失败", null);
	}

	@Override
	public int findCount(Long userId, Long... couponBatchId) {
		return ygCouponDetailMapper.selectCount(userId, couponBatchId != null && couponBatchId.length > 0 ? couponBatchId : null);
	}

	@Override
	public List<YgCouponModel> findOverListForRemind(String overDate, SalesPlatform salesPlatform) {
		Assert.notNull(overDate);
		return ygCouponDetailMapper.selectForOverRemind(overDate, salesPlatform);
	}
}
